#ifndef __MY_DATA__
#define __MY_DATA__

#include "fileUtil.hpp"
#include "config.hpp"

#include <unordered_map>
#include <pthread.h>
#include <vector>
#include "dataBaseManager.hpp"
namespace cloudBackup
{
	// 数据管理类 怎么管理
	class DataManager
	{
	private:
		// 使用hash表在内存中管理数据 以reqDownloadPath作为key值--查询速度快
		// map[reqDownloadPath] = BackupAInfo;浏览器下载文件的时候总是以reqDownloadPath作为请求
		std::unordered_map<std::string, cloudBackup::BackupAInfo> _table;

		// 读写锁：读共享 写互斥
		pthread_rwlock_t _rwlock;

	public:
		DataManager()
		{
			// 成员属性初始化
			//_backupAInfoFile = Config::GetInstance()->GetBackupAInfoFName(); // 获取存放备份文件属性信息的文件
			pthread_rwlock_init(&_rwlock, NULL); // 初始化读写锁
			InitLoad();
		}

		~DataManager()
		{
			pthread_rwlock_destroy(&_rwlock); // 销毁读写锁
		}

		// 程序运行前 从 数据库backup_files 表  中读取数据至内存中的哈希表
		bool InitLoad()
		{
			cloudBackup::DataBaseManager& dbManager = cloudBackup::DataBaseManager::getDBInstance();
			
			if (!dbManager.loadFileAInfo(_table))
			{
				Log::log(FATAL, "DataManager::InitLoad loadFileAInfo %s error!", DB.c_str());
				return false;
			}
			Log::log(INFO, "DataManager::InitLoad load db %s success!", DB.c_str());
			return true;
		}

		// 文件属性信息从数据库到内存
		bool Insert_Table(cloudBackup::BackupAInfo &info)
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info._reqDownloadPath] = info;
			pthread_rwlock_unlock(&_rwlock);
			
			cloudBackup::DataBaseManager& dbManager = cloudBackup::DataBaseManager::getDBInstance();
			_table[info._reqDownloadPath]._backupId = dbManager.insertRecord(info);
			
			return true;
		}

		//与插入不同的是 表中数据更新 需要持久化存储到数据库
		bool Update_Table(const cloudBackup::BackupAInfo &info)
		{
			pthread_rwlock_wrlock(&_rwlock);
			_table[info._reqDownloadPath] = info;
			pthread_rwlock_unlock(&_rwlock);

			cloudBackup::DataBaseManager& dbManager = cloudBackup::DataBaseManager::getDBInstance();
			dbManager.modifyRecord(info);
			return true;
		}

		// 获取某用户当前表中的所有的BackupAInfo 存入array
		bool GetAllBackupAInfo(std::vector<cloudBackup::BackupAInfo> *array, int USRID = 0)
		{
			if (USRID == 0)
			{
				pthread_rwlock_wrlock(&_rwlock);

				for (auto it = _table.begin(); it != _table.end(); ++it)
					array->push_back(it->second);

				pthread_rwlock_unlock(&_rwlock);
				return true;
			}
			else
			{
				pthread_rwlock_wrlock(&_rwlock);

				for (auto it = _table.begin(); it != _table.end(); ++it)
				{
					if (it->second._userId == USRID)
						array->push_back(it->second);
				}

				pthread_rwlock_unlock(&_rwlock);
				return true;
			}
		}

		// http://ip:port/path?id=5&num=4#ch /download/a.txt
		bool GetOneByReqDownloadPath(const std::string &reqDownloadPath, cloudBackup::BackupAInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);
			// reqDownloadPath是key值 直接通过find进行查找
			auto it = _table.find(reqDownloadPath);
			if (it == _table.end())
			{
				pthread_rwlock_unlock(&_rwlock);
				Log::log(LOGERROR, "DataManager::GetOneByReqDownloadPath not find reqDownloadPath-?: %s: %d", strerror(errno), errno);
				return false;
			}
			*info = it->second;
			pthread_rwlock_unlock(&_rwlock);
			return true;
		}

		// /backupDir/a.txt
		bool GetOneByFilePath(const std::string &filePath, cloudBackup::BackupAInfo *info)
		{
			pthread_rwlock_wrlock(&_rwlock);
			for (auto it = _table.begin(); it != _table.end(); ++it)
			{
				if (it->second._backupPath == filePath)
				{
					*info = it->second;
					pthread_rwlock_unlock(&_rwlock);
					return true;
				}
			}
			pthread_rwlock_unlock(&_rwlock);
			Log::log(LOGERROR, "DataManager::GetOneByRealPath not find filepath-?: %s: %d", strerror(errno), errno);
			return false;
		}
	};
}
#endif //__MY_DATA__
